#include <physics/RevoluteJoint.h>

#include <physics/ValueLoader.h>
#include <Box2D/Dynamics/Joints/b2RevoluteJoint.h>

namespace physics
{

RevoluteJoint::RevoluteJoint(World *world)
	: Joint(world)
{
	jointDef.reset(new b2RevoluteJointDef());
}

RevoluteJoint::~RevoluteJoint()
{
}
	
RevoluteJoint::RevoluteJoint(World * world, Node * nodeA, Node  * nodeB, const Vector2 & anchorA, const Vector2 & anchorB, bool collideConnected) : Joint(world)
{
	jointDef.reset(new b2RevoluteJointDef());
	
	bodiesInfo.bodyA = nodeA;
	bodiesInfo.bodyB = nodeB;
	
	GetJointDef()->localAnchorA.x = anchorA.x / 100.0f;
	GetJointDef()->localAnchorA.y = anchorA.y / 100.0f;
	GetJointDef()->localAnchorB.x = anchorB.x / 100.0f;
	GetJointDef()->localAnchorB.y = anchorB.y / 100.0f;

	GetJointDef()->collideConnected = collideConnected;
}

bool RevoluteJoint::on_node(xml::Provider *prov, const std::string &name)
{
	if(name == "LocalAnchorA")
	{
		if(!ValueReader::Read(prov, GetJointDef()->localAnchorA))
			return false;
		
		GetJointDef()->localAnchorA.x /= 100.0f;
		GetJointDef()->localAnchorA.y /= 100.0f;
		
		return true;
	}
	
	if(name == "LocalAnchorB")
	{
		if(!ValueReader::Read(prov, GetJointDef()->localAnchorB))
			return false;
		
		GetJointDef()->localAnchorB.x /= 100.0f;
		GetJointDef()->localAnchorB.y /= 100.0f;
		
		return true;
	}
	
	if(name == "ReferenceAngle")
		return ValueReader::Read(prov, GetJointDef()->referenceAngle);
	if(name == "LowerAngle")
		return ValueReader::Read(prov, GetJointDef()->lowerAngle);
	if(name == "UpperAngle")
		return ValueReader::Read(prov, GetJointDef()->upperAngle);
	if(name == "MaxMotorTorque")
		return ValueReader::Read(prov, GetJointDef()->maxMotorTorque);
	if(name == "MotorSpeed")
		return ValueReader::Read(prov, GetJointDef()->motorSpeed);
	if(name == "EnableLimit")
		return ValueReader::Read(prov, GetJointDef()->enableLimit);
	if(name == "EnableMotor")
		return ValueReader::Read(prov, GetJointDef()->enableMotor);

	return Joint::on_node(prov, name);
}

void RevoluteJoint::SetLimits(bool enabled, float lowerAngle, float upperAngle)
{
	reinterpret_cast<b2RevoluteJoint*>(b2joint)->EnableLimit(enabled);
	reinterpret_cast<b2RevoluteJoint*>(b2joint)->SetLimits(lowerAngle, upperAngle);
}
	
bool RevoluteJoint::IsLimitsEnabled() const
{
	return reinterpret_cast<b2RevoluteJoint*>(b2joint)->IsLimitEnabled();
}
	
float RevoluteJoint::GetLowerAngle() const
{
	return reinterpret_cast<b2RevoluteJoint*>(b2joint)->GetLowerLimit();
}
	
float RevoluteJoint::GetUpperAngle() const
{
	return reinterpret_cast<b2RevoluteJoint*>(b2joint)->GetUpperLimit();
}

}